package org.cloudie.docs.editor.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

import java.util.Date;

import org.cloudie.docs.editor.client.commands.Command;
import org.cloudie.docs.editor.client.commands.generic.BrowserOpenCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentCloseCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentCopyCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentDeleteCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentLoadCommonContentsCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentLoadContentsCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentMakeHomepageCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentRefreshCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentReloadCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentRenameCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentRevisionHistoryCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentSaveAndCloseCommand;
import org.cloudie.docs.editor.client.commands.generic.CurrentDocumentSaveCommand;
import org.cloudie.docs.editor.client.commands.generic.DesktopConfigureCommand;
import org.cloudie.docs.editor.client.commands.generic.DesktopFullScreenCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogAboutCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogFolderNewCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogIconNewCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogPreferencesCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogSplashCommand;
import org.cloudie.docs.editor.client.commands.generic.DialogWindowNewCommand;
import org.cloudie.docs.editor.client.commands.generic.ExistingDocumentLoadCommand;
import org.cloudie.docs.editor.client.commands.generic.ExistingDocumentOpenCommand;
import org.cloudie.docs.editor.client.commands.generic.ExplorerWindowOpenDocumentCommand;
import org.cloudie.docs.editor.client.commands.generic.ExplorerWindowOpenFolderCommand;
import org.cloudie.docs.editor.client.commands.generic.ExplorerWindowOpenVirtualFolderCommand;
import org.cloudie.docs.editor.client.commands.generic.FeedEntryCopyCommand;
import org.cloudie.docs.editor.client.commands.generic.FeedEntryOpenCommand;
import org.cloudie.docs.editor.client.commands.generic.FileDialogListDocumentsCommand;
import org.cloudie.docs.editor.client.commands.generic.FileDialogOpenDocumentCommand;
import org.cloudie.docs.editor.client.commands.generic.FileDialogStarDocumentCommand;
import org.cloudie.docs.editor.client.commands.generic.FileDialogUnstarDocumentCommand;
import org.cloudie.docs.editor.client.commands.generic.NativeAlertCommand;
import org.cloudie.docs.editor.client.commands.generic.NewDocumentLoadCommand;
import org.cloudie.docs.editor.client.commands.generic.NewDocumentStartCommand;
import org.cloudie.docs.editor.client.commands.generic.SplashDialogListDesktopsCommand;
import org.cloudie.docs.editor.client.commands.generic.SystemSignOutCommand;
import org.cloudie.docs.editor.client.commands.generic.SystemUploadDocumentsCommand;
import org.cloudie.docs.editor.client.commands.generic.SystemUploadFileCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryAddCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryCopyCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryFolderAddCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryFolderEmptyCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryFolderRefreshCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryMoveCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryRecycleCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryRemoveCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryRenameCommand;
import org.cloudie.docs.editor.client.commands.generic.VirtualEntryTrashAddCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowAddCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowMinimizeCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowMoveCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowOpenCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowRemoveCommand;
import org.cloudie.docs.editor.client.commands.generic.WindowRestoreCommand;
import org.cloudie.docs.editor.client.content.dialogs.AboutDialog;
import org.cloudie.docs.editor.client.content.dialogs.ActionDialog;
import org.cloudie.docs.editor.client.content.dialogs.ErrorDialog;
import org.cloudie.docs.editor.client.content.dialogs.EtagMismatchErrorDialog;
import org.cloudie.docs.editor.client.content.dialogs.FileListDialog;
import org.cloudie.docs.editor.client.content.dialogs.LoadingDialog;
import org.cloudie.docs.editor.client.content.dialogs.NewFolderDialog;
import org.cloudie.docs.editor.client.content.dialogs.NewIconDialog;
import org.cloudie.docs.editor.client.content.dialogs.NewWindowDialog;
import org.cloudie.docs.editor.client.content.dialogs.PreferencesDialog;
import org.cloudie.docs.editor.client.content.dialogs.SplashDialog;
import org.cloudie.docs.editor.client.events.CommandBus;
import org.cloudie.docs.editor.client.events.CommandEvent;
import org.cloudie.docs.editor.client.events.CommandHandler;
import org.cloudie.docs.editor.client.extended.File;
import org.cloudie.docs.editor.client.extended.FileUploader;
import org.cloudie.docs.editor.client.feeds.docs.FileService;
import org.cloudie.docs.editor.client.feeds.docs.FileServiceAsync;
import org.cloudie.docs.editor.client.feeds.docs.FileServiceEntry;
import org.cloudie.docs.editor.client.feeds.docs.FileUser;
import org.cloudie.docs.editor.client.icons.desktop.FolderDesktopIcon;
import org.cloudie.docs.editor.client.icons.desktop.ShortcutDesktopIcon;
import org.cloudie.docs.editor.client.icons.desktop.TrashDesktopIcon;
import org.cloudie.docs.editor.client.managers.DialogManager;
import org.cloudie.docs.editor.client.parts.DesktopPart;
import org.cloudie.docs.editor.client.parts.HeaderPart;
import org.cloudie.docs.editor.client.parts.MenuPart;
import org.cloudie.docs.editor.client.parts.ToolbarPart;
import org.cloudie.docs.editor.client.resources.icons.IconsHelper;
import org.cloudie.docs.editor.client.serialization.Serializer;
import org.cloudie.docs.editor.client.storage.apps.AppSystem;
import org.cloudie.docs.editor.client.storage.apps.AppSystemEntry;
import org.cloudie.docs.editor.client.storage.items.FolderVirtualSystemEntry;
import org.cloudie.docs.editor.client.storage.items.ShortcutVirtualSystemEntry;
import org.cloudie.docs.editor.client.storage.items.TrashVirtualSystemEntry;
import org.cloudie.docs.editor.client.storage.items.VirtualSystem;
import org.cloudie.docs.editor.client.storage.items.VirtualSystemEntry;
import org.cloudie.docs.editor.client.widgets.DesktopIcon;
import org.cloudie.docs.editor.client.windows.DesktopExplorerWindow;
import org.cloudie.docs.editor.client.windows.DocumentExplorerWindow;
import org.cloudie.docs.editor.client.windows.GenericWindow;

/*
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Cloudie implements EntryPoint, CommandHandler {

  private final FileServiceAsync docService;
	  
  private Serializer serializer;
  private DesktopPart desktop;
  private Preferences preferences;
  private DesktopExplorerWindow desktopExplorerWindow;
  private DocumentExplorerWindow documentExplorerWindow;
  private DialogManager dialogManager;
  private FileUser currentUser;
  private FileServiceEntry currentDocument;
  private FileServiceEntry[] allDocuments;
  private FileServiceEntry[] allLatex;
  private FileServiceEntry[] allDesktops;
  private FlexTable contentPane;
  private HeaderPart header;
  private MenuPart menu;
  private ToolbarPart toolbar;
  
  public Cloudie() {
	docService = GWT.create(FileService.class);
	CommandBus.get().addCommandHandler(this);
  }
  
  /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
	docService.getUser(new AsyncCallback<FileUser>() {
		@Override
		public void onFailure(Throwable caught) {
		  Window.alert("Authentication Failure: " + caught.getMessage());
		}
		@Override
		public void onSuccess(FileUser result) {
  		  if (result == null) {
  		    if (!GWT.isScript()) {
  			  //if running in dev mode, auto-authenticate with a test account
  			  docService.setUser("non.gwt.gdata@gmail.com", "CIuortn_DxDn34Ow______8BGI3qgMsD", new AsyncCallback<FileUser>() {
  				  @Override
  				  public void onFailure(Throwable caught) {
  				  }
  				  @Override
  				  public void onSuccess(FileUser result) {
  	  		        currentUser = result;
  	                start();
  				  }
  			  });
  			} else {
  		      Window.alert("No login detected. Ensure that any requests go through the server side, " +
  		          "to enforce authentication, rather than directly to the HTML " +
  		          "content.");
  			}
  		  } else {
  		    currentUser = result;
            start();
  		  }
		}
	});
  }
  
  private void start() {
	serializer = new Serializer();
	serializer.addCommandHandler(this);
    desktop = new DesktopPart();
    desktop.setSize("100%", "100%");
    preferences = new Preferences();
    contentPane = new FlexTable();
    contentPane.setSize("100%", "100%");
    contentPane.setCellSpacing(0);
    contentPane.setCellPadding(0);
    contentPane.setBorderWidth(0);
    contentPane.insertRow(0);
    contentPane.insertCell(0, 0);
    contentPane.getFlexCellFormatter().setHeight(0, 0, "120px");
    contentPane.insertRow(1);
    contentPane.insertCell(1, 0);
    contentPane.getFlexCellFormatter().setStylePrimaryName(1, 0, "cloudie-desktop-box");
    header = new HeaderPart();
    header.setAuthor(currentUser.getEmail());
    menu = new MenuPart();
    toolbar = new ToolbarPart();
    VerticalPanel headerPanel = new VerticalPanel();
    headerPanel.setWidth("100%");
    headerPanel.add(header);
    headerPanel.add(menu);
    headerPanel.add(toolbar);
    contentPane.setWidget(0, 0, headerPanel);
    contentPane.setWidget(1, 0, desktop);
    RootPanel.get().add(contentPane);
    desktopExplorerWindow = new DesktopExplorerWindow();
    documentExplorerWindow = new DocumentExplorerWindow();
    desktop.addWindow(desktopExplorerWindow, 140, 10);
    desktop.addWindow(documentExplorerWindow, 140, 10);
    desktop.addTrays();
    dialogManager = new DialogManager();
    
    Window.addResizeHandler(new ResizeHandler() {
		@Override
		public void onResize(ResizeEvent event) {
	      desktop.resize();
		}
    });
    
    execute(new DesktopFullScreenCommand());
    loadDocument();
  }
  
  /**
   * Extracts the "docid" parameter from the URL querystring and loads the
   * respective document - the document details are loaded first, followed by
   * the document contents.
   * If "docid" is blank then a new, unsaved, document is loaded.
   */
  public void loadDocument() {
    String documentId = Window.Location.getParameter("docid");
    if (documentId == null || documentId.equals("")) {
      documentId = Window.Location.getHash();
      if (documentId != null && documentId.startsWith("#")) {
    	documentId = documentId.substring(1);
      }
    }
    if (documentId == null || documentId.equals("")) {
      execute(new DialogSplashCommand());
    } else {
      execute(new ExistingDocumentLoadCommand(documentId));
      execute(new SplashDialogListDesktopsCommand());
    }
  }
  
  /**
   * Closes the current window.
   */
  private native void close() /*-{
    $wnd.close();
  }-*/;

  /**
   * Sets the currently open document and updates the header info and window title
   * with the respective document information.
   * 
   * @param doc the document which to use
   * @param requireNewEtag whether a new Etag is expected for the specified document
   */
  private void setDocument(FileServiceEntry doc, boolean requireNewEtag) {
	boolean wasStored = (currentDocument != null && currentDocument.isStored());
	boolean etagSame = false;
	if (currentDocument != null && currentDocument.getEtag() != null) {
      etagSame = currentDocument.getEtag().equals(doc.getEtag());
	}
    currentDocument = doc;
    header.setTitle(doc.getTitle());
    Window.setTitle(doc.getTitle() + " - Cloudie");
    if (currentDocument.isStored()) {
      header.setInfo(currentDocument.getDocumentId(), currentDocument.getEdited(), currentDocument.getEditor());
      if (!wasStored) {
        History.newItem(doc.getDocumentId());
      } else {
	    if (etagSame) {
          if(etagSame && requireNewEtag) {
    	    new Timer() {
	            @Override
		        public void run() {
		          execute(new CurrentDocumentRefreshCommand(true, null));
		        }
            }.schedule(2000);
          }
	    }
      }
    }
  }
  
  /**
   * Shows a status message. If modal, a loading dialog is displayed, otherwise
   * the header status area is used.
   * 
   * @param message the status message to display
   * @param modal whether the status display is modal
   */
  private void showStatus(String message, boolean modal) {
    if (modal) {
      LoadingDialog loadingDialog = LoadingDialog.get();
      loadingDialog.setMessage(message);
      dialogManager.showDialog(loadingDialog);
    } else {
      header.setStatus(message);
    }
  }
  
  /**
   * Clears and hides any visible status messages.
   */
  private void clearStatus() {
	LoadingDialog.get().hide();
    header.setStatus("");
  }

  /**
   * Handles a command error.
   * 
   * @param error the error exception
   * @param command the command that triggered the error
   * @param alternate the command to trigger on cancel
   * @param retryAttempts the number of times to retry the command before displaying an error dialog
   */
  private <E extends Command, V extends Command> void handleError(
	    Throwable error, E command, V alternate, int retryAttempts){
    clearStatus();
    if (command.getAttemptCount() <= retryAttempts) {
      command.newAttempt();
      execute(command);
    } else {
      if (error.getMessage().contains("Mismatch: etags")) {
    	EtagMismatchErrorDialog errorDialog = EtagMismatchErrorDialog.get();
        errorDialog.update(error, command, alternate);
        dialogManager.showDialog(errorDialog);
      } else {
        ErrorDialog errorDialog = ErrorDialog.get();
        errorDialog.update(error, command, alternate);
        dialogManager.showDialog(errorDialog);
      }
    }
  }
  
  public void onCommand(CommandEvent e) {
	execute(e.getCommand());
  }
  
  private void execute(final FileDialogUnstarDocumentCommand cmd){
    docService.setFileStarred(cmd.getDocumentId(),
        false,
        new AsyncCallback<Boolean>(){
          public void onFailure(Throwable caught) {
            handleError(caught, cmd, null, 1);
          }
          public void onSuccess(Boolean result) {
          }
    });
  }
  private void execute(final FileDialogStarDocumentCommand cmd) {
    docService.setFileStarred(
		cmd.getDocumentId(),
        true,
        new AsyncCallback<Boolean>(){
          public void onFailure(Throwable caught) {
            handleError(caught, cmd, null, 1);
          }
          public void onSuccess(Boolean result) {
          }
        }
    );
  }
  private void execute(final FileDialogListDocumentsCommand cmd) {
	if (cmd.isUseCache() && allDesktops != null) {
	  FileListDialog fileListDialog = FileListDialog.get();
      fileListDialog.setEntries(allDesktops);
      fileListDialog.showEntries();
	} else {
      docService.getFiles(false, "cloudie", new AsyncCallback<FileServiceEntry[]>() {
        public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 1);
        }
        public void onSuccess(FileServiceEntry[] result) {
          allDesktops = result;
    	  FileListDialog fileListDialog = FileListDialog.get();
          fileListDialog.setEntries(result);
          fileListDialog.showEntries();
        }
      });
	}
  }
  private void execute(final FileDialogOpenDocumentCommand cmd) {
    Window.open("http://docs.google.com/Doc?docid=" + cmd.getDocumentId() + "&hl=en", cmd.getDocumentId(), "");
  }
  private void execute(final ExplorerWindowOpenDocumentCommand cmd) {
    Window.open("http://docs.google.com/Doc?docid=" + cmd.getDocumentId() + "&hl=en", cmd.getDocumentId(), "");
  }
  private void execute(final ExplorerWindowOpenVirtualFolderCommand cmd) {
	VirtualSystemEntry virtualFolderEntry;
	if (cmd.getFolderId() == null) {
	  virtualFolderEntry = new FolderVirtualSystemEntry(
	      null, "Desktop", "", null, 0, 0, -1);
	} else {
	  virtualFolderEntry = VirtualSystem.getEntry(cmd.getFolderId());
	}
	VirtualSystemEntry[] virtualContentEntries = VirtualSystem.getEntries(cmd.getFolderId());
	desktopExplorerWindow.show(virtualFolderEntry, virtualContentEntries);
  }
  private void execute(final ExplorerWindowOpenFolderCommand cmd) {
	AsyncCallback<FileServiceEntry[]> cb = new AsyncCallback<FileServiceEntry[]>() {
        public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 1);
        }
        public void onSuccess(FileServiceEntry[] result) {
          setFileEntries(result);
	      FileServiceEntry docFolderEntry = new FileServiceEntry();
		  if (cmd.getFolderName() == null) {
	        docFolderEntry.setDocumentId(null);
		    docFolderEntry.setTitle("My Documents");
		  } else {
		    String name = cmd.getFolderName();
	        docFolderEntry.setDocumentId(name);
		    docFolderEntry.setTitle(name);
		    for (FileServiceEntry entry : allDocuments) {
			  if (entry.getType().equalsIgnoreCase("folder") &&
				  entry.getTitle().equals(name)) {
				String parent = entry.getExplorerEntryParentId();
				if (parent != null) docFolderEntry.setFolders(new String[] { parent });
			  }
		    }
		  }
          documentExplorerWindow.show(docFolderEntry, result);
        }
    };
	if (cmd.isUseCache() && allDocuments != null) {
	  cb.onSuccess(allDocuments);
	} else {
	  documentExplorerWindow.setLoading(true);
      docService.getFiles(false, null, cb);
	}
  }
  private void execute(final SplashDialogListDesktopsCommand cmd) {
    docService.getFiles(false, "cloudie", new AsyncCallback<FileServiceEntry[]>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, null, 1);
      }
      public void onSuccess(FileServiceEntry[] result) {
        allDesktops = result;
    	SplashDialog splashDialog = SplashDialog.get();
        splashDialog.setDesktops(result);
      }
    });
  }
  private void execute(final WindowMinimizeCommand cmd) {
	String iconId = VirtualSystem.getNextId();
	VirtualEntryAddCommand wmiCmd = new VirtualEntryAddCommand(
		iconId, cmd.getRestoreCommand().getTitle(), "apps/system_software_update",
		"Restore " + cmd.getRestoreCommand().getTitle() + " window.",
		null, cmd.getRestoreCommand().getX(), cmd.getRestoreCommand().getY(), 0,
		cmd.getRestoreCommand());
	cmd.getRestoreCommand().setIconId(iconId);
    execute(wmiCmd);
    execute(new WindowRemoveCommand(cmd.getWindowId()));
  }
  private void execute(final WindowRestoreCommand cmd) {
	String windowId = cmd.getWindowId();
	String iconId = cmd.getIconId();
	execute(new VirtualEntryRemoveCommand(iconId));
	AppSystemEntry entry = new AppSystemEntry(windowId, cmd.getTitle(),
	  cmd.getContents().getType().name(), cmd.getContents().getValue(),
	  cmd.getX(), cmd.getY(), cmd.getWidth(), cmd.getWidth());
    AppSystem.addEntry(entry);
	GenericWindow window = new GenericWindow(windowId, cmd.getTitle(), cmd.getContents());
    window.setContentSize(cmd.getWidth(), cmd.getHeight());
    desktop.addWindow(window, cmd.getX(), cmd.getY());
  }
  private void execute(final WindowAddCommand cmd) {
	String id = cmd.getWindowId();
	if (id == null) {
	  id = AppSystem.getNextId();
	}
	AppSystemEntry entry = new AppSystemEntry(id, cmd.getTitle(),
	  cmd.getContents().getType().name(), cmd.getContents().getValue(),
	  cmd.getX(), cmd.getY(), cmd.getWidth(), cmd.getWidth());
    AppSystem.addEntry(entry);
	GenericWindow window = new GenericWindow(id, cmd.getTitle(), cmd.getContents());
    window.setContentSize(cmd.getWidth(), cmd.getHeight());
    desktop.addWindow(window, cmd.getX(), cmd.getY());
  }
  private void execute(final WindowMoveCommand cmd) {
	String id = cmd.getWindowId();
	AppSystemEntry entry = AppSystem.getEntry(id);
	if (entry != null) {
      if (cmd.isHasMoved()) {
	    entry.setX(cmd.getNewX());
	    entry.setY(cmd.getNewY());
      }
      if (cmd.isHasResized()) {
	    entry.setWidth(cmd.getNewWidth());
	    entry.setHeight(cmd.getNewHeight());
      }
	}
  }
  private void execute(final DialogWindowNewCommand cmd) {
	dialogManager.showDialog(NewWindowDialog.get());
  }
  private void execute(final WindowRemoveCommand cmd) {
	String id = cmd.getWindowId();
  	AppSystem.removeEntry(id);
  	desktop.removeWindow(id);
  }
  private void execute(final DialogIconNewCommand cmd){
	dialogManager.showDialog(NewIconDialog.get());
  }
  private void execute(final DialogFolderNewCommand cmd){
	dialogManager.showDialog(NewFolderDialog.get());
  }
  private void execute(final FeedEntryCopyCommand cmd) {
	String targetId = cmd.getEntryId();
	AsyncCallback<FileServiceEntry> cb = new AsyncCallback<FileServiceEntry>() {
		@Override
		public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 1);
		}
		@Override
		public void onSuccess(FileServiceEntry result) {
		  Command action;
		  if (result.getType().equalsIgnoreCase("folder")) {
			action = new ExplorerWindowOpenFolderCommand(result.getTitle(), true);
		  } else {
			action = new FeedEntryOpenCommand(result.getType(), result.getDocumentId());
		  }
		  execute(new VirtualEntryAddCommand(
			  null, result.getTitle(),
			  IconsHelper.getMimetypeIconIdentifier(result.getType(), false),
			  "Open " + result.getTitle(),
	          cmd.getParentEntryId(), cmd.getNewX(),
	          cmd.getNewY(), -1, action)
		  );
		}
	};
	if (allDocuments != null) {
	  for (FileServiceEntry entry : allDocuments) {
		if (entry.getDocumentId().equals(targetId)) {
		  cb.onSuccess(entry);
		  return;
		}
	  }
	}
	docService.getFile(cmd.getEntryId(), cb);
  }
  private void execute(final FeedEntryOpenCommand cmd) {
	String type = cmd.getType();
	if (type.equalsIgnoreCase("document")) {
      Window.open("http://docs.google.com/Doc?docid=" + cmd.getEntryId() + "", cmd.getEntryId(), "");
	} else if (type.equalsIgnoreCase("spreadsheet")) {
      Window.open("http://spreadsheets.google.com/ccc?key=" + cmd.getEntryId(), cmd.getEntryId(), "");
	} else if (type.equalsIgnoreCase("presentation")) {
      Window.open("http://docs.google.com/present/edit?id=" + cmd.getEntryId(), cmd.getEntryId(), "");
	} else if (type.equalsIgnoreCase("drawing")) {
      Window.open("http://docs.google.com/drawings/edit?id=" + cmd.getEntryId(), cmd.getEntryId(), "");
	} else if (type.equalsIgnoreCase("desktop")) {
	  Window.open("http://docs.cloudie.org/docs?docid=" + cmd.getEntryId(), cmd.getEntryId(), "");
	} else {
	  Window.alert("No editor available for the specific file type.");
	}
  }
  private void execute(final VirtualEntryTrashAddCommand cmd) {
  	String trashIconId = cmd.getId();
  	if (trashIconId == null) trashIconId = VirtualSystem.getNextId();
    TrashVirtualSystemEntry tvsEntry = new TrashVirtualSystemEntry(
        trashIconId, cmd.getLabel(),
        cmd.getImage(), cmd.getX(), cmd.getY(), cmd.getTray());
    VirtualSystem.addEntry(tvsEntry);
    if (tvsEntry.getParent() == null) {
    	desktop.addIcon(
    	    new TrashDesktopIcon(tvsEntry.getId(), tvsEntry.getLabel(),
    	    VirtualSystem.hasChildren(trashIconId)),
    	    tvsEntry.getX(), tvsEntry.getY(), tvsEntry.getTray(), cmd.isDistribute());
    }
    execute(new VirtualEntryFolderRefreshCommand(tvsEntry.getParent()));
  }
  private void execute(final VirtualEntryFolderAddCommand cmd) {
  	String folderIconId = cmd.getId();
  	if (folderIconId == null) folderIconId = VirtualSystem.getNextId();
  	String label = cmd.getLabel();
  	if (label == null) {
  	  label = Window.prompt("Enter the new folder name:", "New Folder");
  	  if (label == null || label.equals("")) {
  	    return;
  	  }
  	}
      FolderVirtualSystemEntry fvsEntry = new FolderVirtualSystemEntry(
          folderIconId, label,
          cmd.getImage(), cmd.getParent(), cmd.getX(), cmd.getY(), cmd.getTray());
      VirtualSystem.addEntry(fvsEntry);
      if (fvsEntry.getParent() == null) {
        desktop.addIcon(
            new FolderDesktopIcon(fvsEntry.getId(),
      	      fvsEntry.getLabel(), fvsEntry.getImage()),
      	  fvsEntry.getX(), fvsEntry.getY(), fvsEntry.getTray(), cmd.isDistribute());
      }
      execute(new VirtualEntryFolderRefreshCommand(fvsEntry.getParent()));
  }
  private void execute(final VirtualEntryAddCommand cmd) {
  	String scIconId = cmd.getId();
  	if (scIconId == null) scIconId = VirtualSystem.getNextId();
    ShortcutVirtualSystemEntry svsEntry = new ShortcutVirtualSystemEntry(
        scIconId, cmd.getLabel(), cmd.getImage(),
        cmd.getTooltip(), cmd.getParent(),
        cmd.getX(), cmd.getY(), cmd.getTray(), cmd.getAction());
    VirtualSystem.addEntry(svsEntry);
    if (svsEntry.getParent() == null) {
  	  desktop.addIcon(
  	      new ShortcutDesktopIcon(svsEntry.getId(),
  	          svsEntry.getLabel(), svsEntry.getImage(),
  	          svsEntry.getTooltip(), svsEntry.getAction()),
  	      svsEntry.getX(), svsEntry.getY(), svsEntry.getTray(), cmd.isDistribute());
    }
    execute(new VirtualEntryFolderRefreshCommand(svsEntry.getParent()));
  }
  private void execute(final VirtualEntryCopyCommand cmd) {
  	VirtualSystemEntry copyEntry = VirtualSystem.getEntry(cmd.getEntryId());
  	VirtualEntryAddCommand iciaCmd = new VirtualEntryAddCommand(copyEntry.getLabel(),
  	  null, copyEntry.getImage(), copyEntry.getTooltip(), cmd.getParentEntryId(),
  	  cmd.getNewX(), cmd.getNewY(), cmd.getNewTray(), copyEntry.getAction());
  	execute(iciaCmd);
  }
  private void execute(final VirtualEntryRecycleCommand cmd) {
	VirtualSystemEntry[] entries = VirtualSystem.getEntries(null);
	for (VirtualSystemEntry entry : entries) {
	  if (entry instanceof TrashVirtualSystemEntry) {
		VirtualEntryMoveCommand mvCmd =
		    new VirtualEntryMoveCommand(cmd.getEntryId(), entry.getId(), 0, 0, -1);
		execute(mvCmd);
		break;
	  }
	}
  }
  private void execute(final VirtualEntryMoveCommand cmd) {
	VirtualSystemEntry movedEntry = VirtualSystem.getEntry(cmd.getEntryId());
	String prevParent = movedEntry.getParent();
	movedEntry = VirtualSystem.setEntryParent(cmd.getEntryId(), cmd.getParentEntryId());
	movedEntry.setX(cmd.getNewX());
	movedEntry.setY(cmd.getNewY());
	movedEntry.setTray(cmd.getNewTray());
	if (movedEntry.getParent() == null && prevParent != null) {
	  if (movedEntry instanceof FolderVirtualSystemEntry) {
	    desktop.addIcon(
	        new FolderDesktopIcon(movedEntry.getId(),
	            movedEntry.getLabel(), movedEntry.getImage()),
	            movedEntry.getX(), movedEntry.getY(), movedEntry.getTray(), false);
	  } else {
      	desktop.addIcon(
            new ShortcutDesktopIcon(movedEntry.getId(),
                movedEntry.getLabel(), movedEntry.getImage(),
                movedEntry.getTooltip(), movedEntry.getAction()),
                movedEntry.getX(), movedEntry.getY(), movedEntry.getTray(), false);
	  }
	} else if (prevParent == null && movedEntry.getParent() != null) {
	  desktop.removeIcon(movedEntry.getId());
	}
    execute(new VirtualEntryFolderRefreshCommand(prevParent));
    execute(new VirtualEntryFolderRefreshCommand(cmd.getParentEntryId()));
  }
  private void execute(final VirtualEntryRemoveCommand cmd) {
	VirtualSystemEntry removedEntry = VirtualSystem.removeEntry(cmd.getEntryId());
	if (removedEntry != null) {
	  if (removedEntry.getParent() == null) {
	    desktop.removeIcon(removedEntry.getId());
	  }
	}
    execute(new VirtualEntryFolderRefreshCommand(removedEntry.getParent()));
  }
  private void execute(final VirtualEntryRenameCommand cmd) {
	String newLabel = cmd.getNewLabel();
	if (newLabel == null) {
      newLabel = Window.prompt("Enter the new icon label:", cmd.getDefaultLabel());
  	  if (newLabel == null || newLabel.equals("")) {
  	    return;
  	  }
  	}
	VirtualSystemEntry renamedEntry = VirtualSystem.setEntryLabel(cmd.getEntryId(), newLabel);
	if (renamedEntry.getParent() == null) {
	  DesktopIcon icon = desktop.getIcon(renamedEntry.getId());
	  if (icon != null) {
	    icon.setLabel(renamedEntry.getLabel());
	  }
	}
    execute(new VirtualEntryFolderRefreshCommand(renamedEntry.getParent()));
  }
  private void execute(final VirtualEntryFolderRefreshCommand cmd) {
  	String folderId = cmd.getEntryId();
  	VirtualSystemEntry[] childEntries = VirtualSystem.getEntries(cmd.getEntryId());
  	if (desktopExplorerWindow.isVisible()) {
  	  String currentFolderId = desktopExplorerWindow.getCurrentFolder().getExplorerEntryId();
  	  VirtualSystemEntry folder = VirtualSystem.getEntry(currentFolderId);
  	  if (currentFolderId == null && folderId == null) {
  	    desktopExplorerWindow.show(folder, childEntries);
  	  } else if (currentFolderId.equals(folderId)){
  	    desktopExplorerWindow.show(folder, childEntries);
  	  }
  	}
  	DesktopIcon icon = desktop.getIcon(folderId);
  	if (icon != null) {
  	  if (icon instanceof TrashDesktopIcon) {
  		TrashDesktopIcon trashIcon = (TrashDesktopIcon) icon;
  		trashIcon.setEmpty(childEntries.length == 0);
  	  }
  	}
  }
  private void execute(final VirtualEntryFolderEmptyCommand cmd) {
  	String folderId = cmd.getEntryId();
    VirtualSystem.removeChildEntries(folderId);
    execute(new VirtualEntryFolderRefreshCommand(folderId));
  }
  private void execute(final BrowserOpenCommand cmd) {
    Window.open(cmd.getUrl(), cmd.getName(), "");
  }
  private void execute(final NativeAlertCommand cmd) {
    Window.alert(cmd.getMessage());
  }
  private void execute(final NewDocumentStartCommand cmd) {
	Date now = new Date();
    Window.open("/docs", "Untitled" + now.getTime(), "");
  }
  private void execute(final ExistingDocumentOpenCommand cmd) {
  	dialogManager.showDialog(FileListDialog.get());
  }
  private void execute(final CurrentDocumentCopyCommand cmd) {
    showStatus("Copying desktop...", true);
    docService.createSpreadsheet("Copy of " + currentDocument.getTitle(),
    	serializer.toCsv(preferences, VirtualSystem.getEntries(), AppSystem.getEntries()),
        new AsyncCallback<FileServiceEntry>(){
        public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 0);
        }
        public void onSuccess(FileServiceEntry result) {
          clearStatus();
          Window.open("/docs?docid=" + result.getDocumentId(), result.getDocumentId(), "");
        }
    });
  }
  private void execute(final CurrentDocumentSaveCommand cmd) {
    showStatus("Saving...", false);
    docService.saveSpreadsheet(currentDocument.getDocumentId(), currentDocument.getEtag(), currentDocument.getTitle(),
        serializer.toCsv(preferences, VirtualSystem.getEntries(), AppSystem.getEntries()),
        new AsyncCallback<FileServiceEntry>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, null, 0);
      }
      public void onSuccess(FileServiceEntry result) {
        setDocument(result, true);
        clearStatus();
      }
    });
  }
  private void execute(final CurrentDocumentSaveAndCloseCommand cmd) {
    showStatus("Saving desktop...", true);
    docService.saveSpreadsheet(currentDocument.getDocumentId(), currentDocument.getEtag(), currentDocument.getTitle(),
        serializer.toCsv(preferences, VirtualSystem.getEntries(), AppSystem.getEntries()),
        new AsyncCallback<FileServiceEntry>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, null, 0);
      }
      public void onSuccess(FileServiceEntry result) {
        setDocument(result, false);
        clearStatus();
        close();
      }
    });
  }
  private void execute(final CurrentDocumentCloseCommand cmd) {
    close();
  }
  private void execute(final CurrentDocumentRenameCommand cmd) {
    final String newName = Window.prompt("Enter new desktop name:", currentDocument.getTitle());
    if (newName != null && !newName.equals("")) {
      if (currentDocument.isStored()) {
        showStatus("Renaming...", false);
        docService.renameFile(currentDocument.getDocumentId(), newName,
            new AsyncCallback<FileServiceEntry>(){
          public void onFailure(Throwable caught) {
            handleError(caught, cmd, null, 0);
          }
          public void onSuccess(FileServiceEntry result) {
            setDocument(result, true);
            clearStatus();
          }
        });
      } else {
        currentDocument.setTitle(newName);
        setDocument(currentDocument, false);
      }
    }
  }
  private void execute(final CurrentDocumentDeleteCommand cmd) {
    if (Window.confirm("This desktop will be deleted and closed.")) {
      if (currentDocument.isStored()) {
        showStatus("Deleting desktop...", true);
        docService.deleteFile(currentDocument.getDocumentId(), "*", new AsyncCallback<Boolean>() {
          public void onFailure(Throwable caught) {
            handleError(caught, cmd, null, 0);
          }
          public void onSuccess(Boolean result) {
            clearStatus();
            close();
          }
        });
      } else {
        close();
      }
    }
  }
  private void execute(final CurrentDocumentRefreshCommand cmd) {
	if (!cmd.isExecuteInBackground()) {
	  showStatus("Obtaining document metadata...", true);
    }
    docService.getFile(currentDocument.getDocumentId(), new AsyncCallback<FileServiceEntry>() {
      public void onFailure(Throwable caught) {
    	if (!cmd.isExecuteInBackground()) {
          handleError(caught, cmd, null, 1);
    	}
      }
      public void onSuccess(FileServiceEntry result) {
        setDocument(result, false);
        if (!cmd.isExecuteInBackground()) {
          clearStatus();
        }
        if (cmd.getContinueCommand() != null) {
          execute(cmd.getContinueCommand());
        }
      }
    });
  }
  private void execute(final CurrentDocumentReloadCommand cmd) {
  	showStatus("Reloading document...", true);
    Window.Location.assign("/docs?docid=" + currentDocument.getDocumentId() + "&hl=en");
  }
  private void execute(final CurrentDocumentMakeHomepageCommand cmd) {
    if (currentDocument.isStored()) {
      ActionDialog ad = ActionDialog.get();
      ad.update("Set Desktop As Home Page", "OK", "To have the current desktop load every " +
      		"time you start your web browser, update your browser's settings to set " +
      		"the home page to the following URL:<br /><br />http://docs.cloudie.org/docs?docid" + 
      		currentDocument.getDocumentId(), false, null);
      ad.center();
    } else {
      Window.alert("The current desktop has not been saved. Please save the current desktop before setting it as your home page.");
    }
  }
  private void execute(final NewDocumentLoadCommand cmd) {
  	docService.getNewFile("Untitled Desktop", new AsyncCallback<FileServiceEntry>() {
		@Override
		public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 1);
		}
		@Override
		public void onSuccess(FileServiceEntry result) {
	      setDocument(result, false);
	      execute(new CurrentDocumentLoadCommonContentsCommand("default"));
	    }
	});
  }
  private void execute(final ExistingDocumentLoadCommand cmd) {
    showStatus("Loading desktop...", true);
    docService.getFile(cmd.getDocumentId(), new AsyncCallback<FileServiceEntry>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, new NewDocumentLoadCommand(), 1);
      }
      public void onSuccess(FileServiceEntry result) {
        setDocument(result, false);
        clearStatus();
        execute(new CurrentDocumentLoadContentsCommand());
      }
    });
  }
  private void execute(final CurrentDocumentLoadContentsCommand cmd) {
    showStatus("Loading desktop contents...", true);
    docService.getSpreadsheetContents(currentDocument.getDocumentId(),
        new AsyncCallback<String>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, null, 1);
      }
      public void onSuccess(String result) {
        serializer.fromCsv(result);
        clearStatus();
      }
    });
  }
  private void execute(final CurrentDocumentLoadCommonContentsCommand cmd) {
    showStatus("Loading desktop contents...", true);
    docService.getCommonContents("default",
        new AsyncCallback<String>() {
      public void onFailure(Throwable caught) {
        handleError(caught, cmd, null, 1);
      }
      public void onSuccess(String result) {
        serializer.fromCsv(result);
        clearStatus();
      }
    });
  }
  private void execute(final CurrentDocumentRevisionHistoryCommand cmd) {
    Window.open("http://docs.google.com/Revs?id=" +
        currentDocument.getDocumentId() + "&tab=revlist",
        currentDocument.getDocumentId(), "");
  }
  private void execute(final DialogAboutCommand cmd) {
  	dialogManager.showDialog(AboutDialog.get());
  }
  private void execute(final DialogPreferencesCommand cmd) {
	PreferencesDialog pd = PreferencesDialog.get(
	    preferences.getBackgroundColor(),
	    preferences.getBackgroundImage(),
	    preferences.getIconTextColor(),
	    preferences.getIconBackgroundColor()
	);
  	dialogManager.showDialog(pd);
  }
  private void execute(final DialogSplashCommand cmd) {
  	dialogManager.showDialog(SplashDialog.get());
  }
  private void execute(final DesktopConfigureCommand cmd) {
    preferences.setBackgroundColor(cmd.getBackgroundColor());
    preferences.setBackgroundImage(cmd.getBackgroundImage());
    preferences.setBackgroundPosition(cmd.getBackgroundPosition());
    preferences.setBackgroundRepeat(cmd.getBackgroundRepeat());
    preferences.setIconTextColor(cmd.getIconTextColor());
    preferences.setIconBackgroundColor(cmd.getIconBackgroundColor());
    desktop.setStyle(cmd.getBackgroundColor(),
        cmd.getBackgroundImage(),
        cmd.getBackgroundPosition(),
        cmd.getBackgroundRepeat(),
        cmd.getIconTextColor(),
        cmd.getIconBackgroundColor());
  }
  private void execute(final DesktopFullScreenCommand cmd) {
    boolean isFullScreen = !header.isVisible();
    if (isFullScreen) {
      menu.setMenuItemIcon("Full-screen mode", IconsHelper.icons.Blank());
      menu.setVisible(true);
      header.setVisible(true);
      contentPane.getFlexCellFormatter().setHeight(0, 0, "120px");
    } else {
      menu.setMenuItemIcon("Full-screen mode", IconsHelper.icons.CheckBlack());
      menu.setVisible(false);
      header.setVisible(false);
      contentPane.getFlexCellFormatter().setHeight(0, 0, "30px");
    }
    desktop.resize();
  }
  private void execute(final SystemSignOutCommand cmd) {
    showStatus("Signing out...", true);
    docService.logout(new AsyncCallback<String>() {
		@Override
		public void onFailure(Throwable caught) {
          handleError(caught, cmd, null, 1);
		}
		@Override
		public void onSuccess(String result) {
          clearStatus();
          Window.Location.replace(cmd.getReturnUrl());
		}
    });
  }
  private void execute(final SystemUploadDocumentsCommand cmd) {
    Window.open("http://docs.google.com/DocAction?action=updoc&hl=en", "UploadDocuments", "");
  }
  
  /**
   * Handles a command event. This is where all the components converge along with
   * the application logic.
   * 
   * @param the command event
   */
  public <T extends Command> void execute(final T cmd) {
    switch (cmd.getCommandId()) {
      case FileDialogUnstarDocumentCommand.serialUid: execute((FileDialogUnstarDocumentCommand) cmd); break;
      case FileDialogStarDocumentCommand.serialUid: execute((FileDialogStarDocumentCommand) cmd); break;
      case FileDialogListDocumentsCommand.serialUid: execute((FileDialogListDocumentsCommand) cmd); break;
      case FileDialogOpenDocumentCommand.serialUid: execute((FileDialogOpenDocumentCommand) cmd); break;
      case ExplorerWindowOpenDocumentCommand.serialUid: execute((ExplorerWindowOpenDocumentCommand) cmd); break;
      case ExplorerWindowOpenVirtualFolderCommand.serialUid: execute((ExplorerWindowOpenVirtualFolderCommand) cmd); break;
      case ExplorerWindowOpenFolderCommand.serialUid: execute((ExplorerWindowOpenFolderCommand) cmd); break;
      case SplashDialogListDesktopsCommand.serialUid: execute((SplashDialogListDesktopsCommand) cmd); break;
      case WindowMinimizeCommand.serialUid: execute((WindowMinimizeCommand) cmd); break;
      case WindowRestoreCommand.serialUid: execute((WindowRestoreCommand) cmd); break;
      case WindowOpenCommand.serialUid:
      case WindowAddCommand.serialUid: execute((WindowAddCommand) cmd); break;
      case WindowMoveCommand.serialUid: execute((WindowMoveCommand) cmd); break;
      case DialogWindowNewCommand.serialUid: execute((DialogWindowNewCommand) cmd); break;
      case WindowRemoveCommand.serialUid: execute((WindowRemoveCommand) cmd); break;
      case DialogIconNewCommand.serialUid: execute((DialogIconNewCommand) cmd); break;
      case DialogFolderNewCommand.serialUid: execute((DialogFolderNewCommand) cmd); break;
      case FeedEntryCopyCommand.serialUid: execute((FeedEntryCopyCommand) cmd); break;
      case FeedEntryOpenCommand.serialUid: execute((FeedEntryOpenCommand) cmd); break;
      case VirtualEntryTrashAddCommand.serialUid: execute((VirtualEntryTrashAddCommand) cmd); break;
      case VirtualEntryFolderAddCommand.serialUid: execute((VirtualEntryFolderAddCommand) cmd); break;
      case VirtualEntryAddCommand.serialUid: execute((VirtualEntryAddCommand) cmd); break;
      case VirtualEntryCopyCommand.serialUid: execute((VirtualEntryCopyCommand) cmd); break;
      case VirtualEntryMoveCommand.serialUid: execute((VirtualEntryMoveCommand) cmd); break;
      case VirtualEntryRecycleCommand.serialUid: execute((VirtualEntryRecycleCommand) cmd); break;
      case VirtualEntryRemoveCommand.serialUid: execute((VirtualEntryRemoveCommand) cmd); break;
      case VirtualEntryRenameCommand.serialUid: execute((VirtualEntryRenameCommand) cmd); break;
      case VirtualEntryFolderRefreshCommand.serialUid: execute((VirtualEntryFolderRefreshCommand) cmd); break;
      case VirtualEntryFolderEmptyCommand.serialUid: execute((VirtualEntryFolderEmptyCommand) cmd); break;
      case BrowserOpenCommand.serialUid: execute((BrowserOpenCommand) cmd); break;
      case NativeAlertCommand.serialUid: execute((NativeAlertCommand) cmd); break;
      case NewDocumentStartCommand.serialUid: execute((NewDocumentStartCommand) cmd); break;
      case ExistingDocumentOpenCommand.serialUid: execute((ExistingDocumentOpenCommand) cmd); break;
      case CurrentDocumentCopyCommand.serialUid: execute((CurrentDocumentCopyCommand) cmd); break;
      case CurrentDocumentSaveCommand.serialUid: execute((CurrentDocumentSaveCommand) cmd); break;
      case CurrentDocumentSaveAndCloseCommand.serialUid: execute((CurrentDocumentSaveAndCloseCommand) cmd); break;
      case CurrentDocumentCloseCommand.serialUid: execute((CurrentDocumentCloseCommand) cmd); break;
      case CurrentDocumentRenameCommand.serialUid: execute((CurrentDocumentRenameCommand) cmd); break;
      case CurrentDocumentDeleteCommand.serialUid: execute((CurrentDocumentDeleteCommand) cmd); break;
      case CurrentDocumentRefreshCommand.serialUid: execute((CurrentDocumentRefreshCommand) cmd); break;
      case CurrentDocumentReloadCommand.serialUid: execute((CurrentDocumentReloadCommand) cmd); break;
      case CurrentDocumentMakeHomepageCommand.serialUid: execute((CurrentDocumentMakeHomepageCommand) cmd); break;
      case NewDocumentLoadCommand.serialUid: execute((NewDocumentLoadCommand) cmd); break;
      case ExistingDocumentLoadCommand.serialUid: execute((ExistingDocumentLoadCommand) cmd); break;
      case CurrentDocumentLoadContentsCommand.serialUid: execute((CurrentDocumentLoadContentsCommand) cmd); break;
      case CurrentDocumentLoadCommonContentsCommand.serialUid: execute((CurrentDocumentLoadCommonContentsCommand) cmd); break;
      case CurrentDocumentRevisionHistoryCommand.serialUid: execute((CurrentDocumentRevisionHistoryCommand) cmd); break;
      case DialogAboutCommand.serialUid: execute((DialogAboutCommand) cmd); break;
      case DialogPreferencesCommand.serialUid: execute((DialogPreferencesCommand) cmd); break;
      case DialogSplashCommand.serialUid: execute((DialogSplashCommand) cmd); break;
      case DesktopConfigureCommand.serialUid: execute((DesktopConfigureCommand) cmd); break;
      case DesktopFullScreenCommand.serialUid: execute((DesktopFullScreenCommand) cmd); break;
      case SystemSignOutCommand.serialUid: execute((SystemSignOutCommand) cmd); break;
      case SystemUploadDocumentsCommand.serialUid: execute((SystemUploadDocumentsCommand) cmd); break;
      case SystemUploadFileCommand.serialUid:
    	SystemUploadFileCommand sufCmd = (SystemUploadFileCommand) cmd;
    	File file = sufCmd.getFile();
    	if (file.getSize() <= 1000000) {
    	  execute(new VirtualEntryAddCommand(null, file.getName(),
    	      IconsHelper.getMimetypeIconIdentifier(file.getType(), false),
    	      "Open " + sufCmd.getFile().getName(), null, 0, 0, -1, null));
    	  final FileUploader fu = FileUploader.getInstance();
    	  fu.uploadFile("/upload", file, new Runnable() {
			@Override
			public void run() {
			  Window.alert("loaded");
			}
    	  }, new Runnable() {
			@Override
			public void run() {
			  Window.alert("progress: " + fu.getProgress());
			}
    	  }, new Runnable() {
			@Override
			public void run() {
			  Window.alert("error");
			}
    	  });
    	} else {
    	  Window.alert("File size exceeds the maximum allowed size of 1Mb.");
    	}
    	break;
      default:
        Window.alert("Not implemented");
        break;
    }
  }
  
  private void setFileEntries(FileServiceEntry[] entries) {
	allDocuments = entries;
	detectTypes(entries);
  }
  
  private void detectTypes(FileServiceEntry[] entries) {
	if (allDesktops != null) {
	  for (FileServiceEntry desktop : allDesktops) {
		if (desktop.getType().equals("spreadsheet")) {
	      for (FileServiceEntry entry : entries) {
		    if (entry.equals(desktop)) {
	          entry.setType("desktop");
	          break;
		    }
	      }
		}
 	  }
	}
	if (allLatex != null) {
	  for (FileServiceEntry latex : allLatex) {
	    for (FileServiceEntry entry : entries) {
		  if (entry.equals(latex)) {
	        entry.setType("tex");
	        break;
		  }
	    }
 	  }
	}
  }
}
